const webpack = require('webpack');
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const FriendlyErrorsPlugin = require('@fet/friendly-errors-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const SendZipDirWebpackPlugin = require('@liepin/send-zip-dir-webpack-plugin');
const MapWebpackPlugin = require('../../plugins/map-webpack-plugin');
const { webpackConfig } = require('./config');
const { paths, version, log } = require('../../utils');
const _ = require('lodash');

const packageFile = require(path.join(paths.roots, 'package.json'));

const fs = require('fs');

module.exports = function (options) {
  let isProd = process.env.mode === 'production';

  function dllCreate() {
    return Object.keys(options.dll).reduce((a, b) => {
      a['DllReferencePlugin'] = new webpack.DllReferencePlugin({
        context: paths.roots,
        manifest: require(path.join(paths.staticPath, `js/common/${b}.${isProd ? 'prd' : 'dev'}.manifest.json`))
      })
      return a;
    }, {});
  }
  let sendSourceMapData = {
    name: `${paths.projectName}-sourcemap.zip`, // 压缩后的文件名, 可以不指定
    dir: paths.sourcemapAsset, // 需要发送的文件夹的绝对路径, * 必须
    url: 'http://monitor.lietou.com/saveSourcemap', // 服务器接口， * 必须
    data: { // 随着服务端接口发送的数据
      projectName: paths.projectName
    },
    success: data => {
      log.success(data || 'source-map文件已发送至前端日志平台！');
    }
  };
  if(_.isPlainObject(options.sendSourceMap)){
    sendSourceMapData = {
      ...sendSourceMapData,
      ...options.sendSourceMap
    }
  }

  return {
    ...dllCreate(),
    CopyWebpackPlugin: new CopyWebpackPlugin([
      {
        from: path.join(paths.contextPath, 'static'),
        to: path.join(isProd ? paths.prdPath : paths.devPath, isProd ? 'static/[path][name].[hash:8].[ext]' : 'static/[path][name].[ext]'),
        ignore: [
          '.*',
          '*/common/*.json',
          !isProd ? '*.prd*.js' : '*.dev.js'
        ],
        transformPath(targetPath) {
          if (/\/common\/.*\.(dev|prd).*?\.js$/.test(targetPath)) {
            return targetPath.replace(/\.prd|\.dev/, '');
          }
          return targetPath;
        }
      }
    ]),
    MiniCssExtractPlugin: new MiniCssExtractPlugin({
      filename: isProd ? 'css/[name].[hash:8].css' : 'css/[name].css',
      chunkFilename: isProd ? 'css/chunks/[name].[hash:8].css' : 'css/chunks/[name].css',
    }),
    FriendlyErrorsPlugin: new FriendlyErrorsPlugin({
      compilationSuccessInfo: {
        messages: process.env.mode === 'serverHot' && [
          ` 运行项目: ${packageFile.client.projectName}`,
          ` 端口: ${webpackConfig.devServer.port}`
        ],
      },
      warningsFilter(warnings) {
        return warnings.filter(v => !/Conflicting order between/gm.test(v));
      }
    }),
    HtmlWebpackPlugin: new HtmlWebpackPlugin({
      inject: false,
      template: path.join(paths.srcPath, 'pages/home/index.html')
    }),
    OptimizeCSSAssetsPlugin: new OptimizeCSSAssetsPlugin(),
    MapWebpackPlugin: new MapWebpackPlugin({ targetFile: '../map.json' }),
    HashedModuleIdsPlugin: new webpack.HashedModuleIdsPlugin(),
    HtmlWebpackPlugin_prd: new HtmlWebpackPlugin({
      inject: false,
      templateContent(arg) {
        let mapJson = createMapJson(arg.webpack.assets);
        let htmlSnippets = fs.readFileSync(path.join(paths.srcPath, 'pages/home/index.html'), 'utf-8');
        return htmlReplaceUrlHash(htmlSnippets, mapJson);
      }
    }),
    ProgressPlugin: new webpack.ProgressPlugin(),
    CleanWebpackPlugin: new CleanWebpackPlugin({
      cleanStaleWebpackAssets: false, // 不允许删除未使用的文件
    }),
    SendSourceMapWebpackPlugin: new SendZipDirWebpackPlugin(sendSourceMapData)
  }
}

function createMapJson(assets) {
  const regPath = /^(static)\//;
  let mapJson = {};
  assets.forEach(v => {
    let exts = path.extname(v.name);
    if (v.chunkNames.length || regPath.test(v.name)) {
      let key = v.name.replace(exts, '').replace(/\.[a-z0-9]+$/, '') + exts;
      mapJson[path.join(version, key)] = path.join(version, v.name);
    }
  });
  return mapJson;
}

function htmlReplaceUrlHash(htmlSnippets, mapJson) {
  htmlSnippets = htmlSnippets.replace(/concat.lietou-static.com\/(.*?\/)((v5\/.+)(\.js|\.css))/gmi, function (all, $1, $2, $3, $4) {
    return `concat.lietou-static.com/${$1}${mapJson[$2]}`
  });
  return htmlSnippets;
}